﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TCP多人聊天室客户端
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// 客户端套接字
        /// </summary>
        Socket client;

        public MainForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 连接服务端
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Connect_Click(object sender, EventArgs e)
        {
            if (client?.Connected == true)
            {
                MessageBox.Show("已经连接到服务端，无需重复连接");
                return;
            }

            try
            {
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

                string ipv4 = this.textBox_Ip.Text.Trim();
                int port = int.Parse(this.textBox_Port.Text.Trim());

                //连接服务端套接字
                client.Connect(ipv4, port);

                ShowMessage("成功连接到服务端");

                Task.Run(() =>
                {
                    while (true)
                    {
                        try
                        {
                            byte[] buffer = new byte[1024 * 1024];
                            int length = client.Receive(buffer);
                            if (length == 0)
                            {
                                try
                                {
                                    client.Shutdown(SocketShutdown.Both);
                                    client.Close();
                                    ShowMessage("服务端断开了您的连接");
                                }
                                catch { }
                                break;
                            }
                            string message = Encoding.Default.GetString(buffer, 0, length);
                            ShowMessage(message);
                        }
                        catch
                        {
                            break;
                        }
                    }
                });
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
        }

        delegate void MyDelegate();
        private void ShowMessage(string message)
        {
            this.richTextBox_Message.Invoke(new MyDelegate(() =>
            {
                if (this.richTextBox_Message.TextLength > 1024 * 1024)
                {
                    this.richTextBox_Message.Clear();
                }
                this.richTextBox_Message.AppendText($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]\r\n{message}\r\n\r\n");
            }));
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Cut_Click(object sender, EventArgs e)
        {
            if (client?.Connected == false)
            {
                MessageBox.Show("暂未连接，无法断开");
                return;
            }

            try
            {
                client.Shutdown(SocketShutdown.Both);
                client.Close();
                ShowMessage("成功断开连接");
            }
            catch { }
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Send_Click(object sender, EventArgs e)
        {
            if (client?.Connected != true)
            {
                MessageBox.Show("请先连接服务端");
                return;
            }

            string message = this.textBox_Message.Text.Trim();
            if (message.Length == 0)
            {
                MessageBox.Show("请不要发送空字符");
                return;
            }

            byte[] buffer = Encoding.Default.GetBytes(message);
            try
            {
                client.Send(buffer);
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
        }
    }
}
